﻿using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Helper;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace ArtMath.Component.Polygon
{
    /// <summary>
    /// 梯形
    /// </summary>
    [Serializable]
    public class Trapezoid : TrapezoidBase
    {
        public Trapezoid(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.tx, addToList)
        {
        }
        public override void ComponentBuilding(Base component)
        {
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
            if (OrderIndex == 0)
            {
                if (component == Waist2)
                {
                    Waist2.AllowFix = false;
                    Waist2.SpareCoordinate_ = Utility.GetCrossPoint(Waist2.Point1.Pxy, Waist2.PSlope, Waist1.Point1.Pxy, Hemline1.PSlope);
                    Waist2.AllowFix = true;
                    PointD h2 = Pad.PxyToXY(Waist2.SpareCoordinate);
                    double db2len = Waist1.Point1.ToPointD().DistanceTo(h2);
                    Circumference = Waist1.Length + Hemline1.Length + Waist2.Length + db2len;
                    Area = Math.Abs((db2len + Hemline1.Length) * Math.Sqrt((db2len + Waist1.Length - Hemline1.Length + Waist2.Length) * (db2len - Waist1.Length - Hemline1.Length + Waist2.Length) * (db2len + Waist1.Length - Hemline1.Length - Waist2.Length) * (Waist1.Length - db2len + Hemline1.Length + Waist2.Length)) / 4 / (db2len - Hemline1.Length));
                    BaryCenter = Utility.GetBaryCenter(new PointD[] { Waist1.Point1.ToPointD(), Hemline1.Point1.ToPointD(), Waist2.Point1.ToPointD(), h2 });
                }
                else
                {
                    return;
                }
            }
            else
            {
                if (component == Hemline2)
                {
                    Hemline2.SpareCoordinate_ = Hemline2.SpareCoordinate.GetProjectivePoint(Hemline2.Point1.Pxy, Hemline1.PSlope);
                    PointD w2 = Pad.PxyToXY(Hemline2.SpareCoordinate);
                    double y2len = Hemline1.Point1.ToPointD().DistanceTo(w2);
                    Circumference = Waist1.Length + Hemline1.Length + y2len + Hemline2.Length;
                    Area = Math.Abs((Hemline2.Length + Hemline1.Length) * Math.Sqrt((Hemline2.Length + Waist1.Length - Hemline1.Length + y2len) * (Hemline2.Length - Waist1.Length - Hemline1.Length + y2len) * (Hemline2.Length + Waist1.Length - Hemline1.Length - y2len) * (Waist1.Length - Hemline2.Length + Hemline1.Length + y2len)) / 4 / (Hemline2.Length - Hemline1.Length));
                    BaryCenter = Utility.GetBaryCenter(new PointD[] { Hemline1.Point1.ToPointD(), Waist1.Point1.ToPointD(), Hemline2.Point1.ToPointD(), w2 });
                }
                else
                {
                    return;
                }
            }
            base.ComponentBuilding(component);
        }
        public override void InternalPointMove(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 2:
                    PointD[] tmp;
                    if (movePoint == Waist2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, OrderIndex == 0 ? Hemline1.Point1.NewXY : Hemline2.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { OrderIndex == 0 ? Hemline2.Point1.NewXY : Hemline1.Point1.NewXY });
                            if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            Waist1.Point1.Move(tmp[0]);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = new PointD[] { Hemline1.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            else
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Waist1.Point1.NewXY, controlledInPointsOriginalInfo);
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            Hemline1.Point1.Move(tmp[0]);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Hemline1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Waist1.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            else
                            {
                                tmp = new PointD[] { Hemline2.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            Hemline2.Point1.Move(tmp[0]);
                        }
                    }
                    else if (movePoint == Waist1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, OrderIndex == 0 ? Hemline2.Point1.NewXY : Hemline1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { OrderIndex == 0 ? Hemline1.Point1.NewXY : Hemline2.Point1.NewXY });
                            if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            Waist2.Point1.Move(tmp[0]);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Hemline2.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Waist2.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            else
                            {
                                tmp = new PointD[] { Hemline1.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            Hemline1.Point1.Move(tmp[0]);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = new PointD[] { Hemline2.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            else
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Hemline1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Waist2.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            Hemline2.Point1.Move(tmp[0]);
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = new PointD[] { Waist2.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            else
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Waist1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Hemline2.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            Waist2.Point1.Move(tmp[0]);
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Waist2.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Hemline2.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            else
                            {
                                tmp = new PointD[] { Waist1.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            Waist1.Point1.Move(tmp[0]);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, OrderIndex == 0 ? Waist2.Point1.NewXY : Waist1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { OrderIndex == 0 ? Waist1.Point1.NewXY : Waist2.Point1.NewXY });
                            if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            Hemline2.Point1.Move(tmp[0]);
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Waist1.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Hemline1.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            else
                            {
                                tmp = new PointD[] { Waist2.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            Waist2.Point1.Move(tmp[0]);
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                tmp = new PointD[] { Waist1.Point1.NewPxy + movePoint.NewPxy - movePoint.Pxy };
                            }
                            else
                            {
                                tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, Waist2.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { Hemline1.Point1.NewXY });
                                if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            }
                            Waist1.Point1.Move(tmp[0]);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            tmp = Utility.Rotate(controlPointOriginalCoordinate, movePoint.NewXY, OrderIndex == 0 ? Waist1.Point1.NewXY : Waist2.Point1.NewXY, controlledInPointsOriginalInfo, new PointD[] { OrderIndex == 0 ? Waist2.Point1.NewXY : Waist1.Point1.NewXY });
                            if (Pad.Coordinate != null) tmp[0] = Pad.Coordinate.XYToPxy(tmp[0]);
                            Hemline1.Point1.Move(tmp[0]);
                        }
                    }
                    return;
            }
            base.InternalPointMove(movePoint, sender);
        }
        public override void InternalPrepare(PointBase movePoint, ShapeBase sender = null)
        {
            if (CountMovablePoints() == 2 && sender == null)
            {
                controlPointOriginalCoordinate = movePoint.ToPointD();
                double rateDB;
                if (movePoint == Waist1.Point1)
                {
                    if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            rateDB = Hemline1.Length / Hemline2.Length;
                        }
                        else
                        {
                            rateDB = Hemline2.Length / Hemline1.Length;
                        }
                        controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist2.Point1.ToPointD(), rateDB) };
                    }
                    else if (Hemline1.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline1.Point1.ToPointD(), Hemline1.Length / Hemline2.Length) };
                        }
                    }
                    else if (Hemline2.Point1.Movable)
                    {
                        if (OrderIndex == 1)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline2.Point1.ToPointD(), Hemline2.Length / Hemline1.Length) };
                        }
                    }
                }
                else if (movePoint == Waist2.Point1)
                {
                    if (Waist1.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            rateDB = Hemline2.Length / Hemline1.Length;
                        }
                        else
                        {
                            rateDB = Hemline1.Length / Hemline2.Length;
                        }
                        controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist1.Point1.ToPointD(), rateDB) };
                    }
                    else if (Hemline1.Point1.Movable)
                    {
                        if (OrderIndex == 1)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline1.Point1.ToPointD(), Hemline1.Length / Hemline2.Length) };
                        }
                    }
                    else if (Hemline2.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline2.Point1.ToPointD(), Hemline2.Length / Hemline1.Length) };
                        }
                    }
                }
                else if (movePoint == Hemline1.Point1)
                {
                    if (Waist1.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist1.Point1.ToPointD(), Hemline2.Length / Hemline1.Length) };
                        }
                    }
                    else if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 1)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist2.Point1.ToPointD(), Hemline2.Length / Hemline1.Length) };
                        }
                    }
                    else if (Hemline2.Point1.Movable)
                    {
                        controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline2.Point1.ToPointD(), Hemline2.Length / Hemline1.Length) };
                    }
                }
                else if (movePoint == Hemline2.Point1)
                {
                    if (Waist1.Point1.Movable)
                    {
                        if (OrderIndex == 1)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist1.Point1.ToPointD(), Hemline1.Length / Hemline2.Length) };
                        }
                    }
                    else if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 0)
                        {
                            controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Waist2.Point1.ToPointD(), Hemline1.Length / Hemline2.Length) };
                        }
                    }
                    else if (Hemline1.Point1.Movable)
                    {
                        controlledInPointsOriginalInfo = new KeyValuePair<PointD, double>[] { new KeyValuePair<PointD, double>(Hemline1.Point1.ToPointD(), Hemline1.Length / Hemline2.Length) };
                    }
                }
            }
            base.InternalPrepare(movePoint, sender);
        }
        public override bool CanDrawVirtual
        {
            get
            {
                if (OrderIndex == 0)
                {
                    return Waist2 != null;
                }
                else
                {
                    return Hemline2 != null;
                }
            }
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            if (CanDrawVirtual)
            {
                if (OrderIndex == 0)
                {
                    gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Waist1.Point1.Pxy.ToPointF(), Hemline1.Point1.Pxy.ToPointF(), Waist2.Point1.Pxy.ToPointF(), Waist2.SpareCoordinate_.ToPointF() });
                    gra.DrawLineSegment(Waist2.SpareCoordinate_, Waist1.Point1.Pxy);
                }
                else
                {
                    gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Hemline1.Point1.Pxy.ToPointF(), Waist1.Point1.Pxy.ToPointF(), Hemline2.Point1.Pxy.ToPointF(), Hemline2.SpareCoordinate_.ToPointF() });
                    gra.DrawLineSegment(Hemline2.SpareCoordinate_, Hemline1.Point1.Pxy);
                }
            }
        }
        protected override void ClickOrder(IList<PointCreatingArgs> args, int clickTimes, Predicate<PointCreatingArgs> act)
        {
            if (act == null) return;
            if (OrderIndex == 1)
            {
                if (!act(args[1])) return;
                if (!act(args[0])) return;
                if (!act(args[3])) return;
                if (!act(args[2])) return;
                return;
            }
            base.ClickOrder(args, clickTimes, act);
        }
        public override void CreateComponents()
        {
            if (OrderIndex == 0)
            {
                if (Waist1 == null)
                {
                    Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                    Waist1.CreateComponents($"{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}2");
                }
                else if (Hemline1 == null)
                {
                    Waist1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                    Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false);
                    Hemline1.CreateComponents(Waist1.Point2);
                }
                else if (Waist2 == null)
                {
                    Hemline1.CreateComponents($"{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                    Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}2", false);
                    Waist2.CreateComponents(Hemline1.Point2);
                }
                else
                {
                    Waist2.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new Ray(Waist1.Point1.ToPointD(), Hemline1.Point1.ToPointD().GetAngle(Waist2.Point1.ToPointD())) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Waist2.Point1.ToPointD(), Waist1.Slope) } } });
                    Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                    Hemline2.CreateComponents(Waist2.Point2, Waist1.Point1);
                    base.CreateComponents();
                }
            }
            else
            {
                if (Hemline1 == null)
                {
                    Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                    Hemline1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("EndPoint")}2");
                }
                else if (Waist1 == null)
                {
                    Hemline1.CreateComponents($"{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                    Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}1", false);
                    Waist1.CreateComponents(Hemline1.Point2);
                }
                else if (Hemline2 == null)
                {
                    Waist1.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                    Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false) { AllowFix = false };
                    Hemline2.CreateComponents(Waist1.Point2);
                }
                else
                {
                    Hemline2.CreateComponents($"{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new Ray(Hemline2.Point1.ToPointD(), Waist1.Point1.ToPointD().GetAngle(Hemline1.Point1.ToPointD())) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Hemline1.Point1.ToPointD(), Waist1.Slope) } } });
                    Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}2", false);
                    Waist2.CreateComponents(Hemline2.Point2, Hemline1.Point1);
                    base.CreateComponents();
                }
            }
        }
    }
}
